home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright 1991,1992 Eric R. Smith.
- Copyright 1992,1993,1994 Atari Corporation.
- All rights reserved.
- */
-
- #include "mint.h"
- #include "fasttext.h"
-
- #ifdef FASTTEXT
-
- #ifdef __GNUC__
- #define INLINE inline
- #define ITYPE long /* gcc's optimizer likes 32 bit integers */
- #else
- #define INLINE
- #define ITYPE int
- #endif
-
- #define CONDEV (2)
-
- static SCREEN *current;
- static short scr_usecnt;
-
- static void paint P_((SCREEN *, int, char *)),
- paint8c P_((SCREEN *, int, char *)),
- paint816m P_((SCREEN *, int, char *));
-
- INLINE static void curs_off P_((SCREEN *)), curs_on P_((SCREEN *));
- INLINE static void flash P_((SCREEN *));
- static void normal_putch P_((SCREEN *, int));
- static void escy_putch P_((SCREEN *, int));
- static void quote_putch P_((SCREEN *, int));
-
- static char *chartab[256];
-
- #define MAX_PLANES 8
- static int fgmask[MAX_PLANES], bgmask[MAX_PLANES];
-
- static long scrnsize;
-
- short hardscroll;
- static char *hardbase, *oldbase;
-
- typedef void (*Vfunc) P_((SCREEN *, int));
-
- #define base *((char **)0x44eL)
- #define escy1 *((short *)0x4acL)
-
- static Vfunc state;
-
- static short hardline;
- static void (*vpaint) P_((SCREEN *, int, char *));
- static char *rowoff;
-
- void init P_((void));
- void hardware_scroll P_((SCREEN *));
- INLINE static char *PLACE P_((SCREEN *, int, int));
- INLINE static void gotoxy P_((SCREEN *, int, int));
- INLINE static void clrline P_((SCREEN *, int));
- INLINE static void clear P_((SCREEN *));
- INLINE static void clrchar P_((SCREEN *, int, int));
- INLINE static void clrfrom P_((SCREEN *, int, int, int, int));
- INLINE static void delete_line P_((SCREEN *, int));
- INLINE static void insert_line P_((SCREEN *, int));
- static void setbgcol P_((SCREEN *, int));
- static void setfgcol P_((SCREEN *, int));
- static void setcurs P_((SCREEN *, int));
- static void putesc P_((SCREEN *, int));
- static void escy1_putch P_((SCREEN *, int));
- INLINE static void put_ch P_((SCREEN *, int));
-
- /* routines for flashing the cursor for screen v */
- /* flash(v): invert the character currently under the cursor */
-
- INLINE static void
- flash(v)
- SCREEN *v;
- {
- char *place;
- ITYPE i, j, vplanes;
-
- vplanes = v->planes + v->planes;
- place = v->cursaddr;
-
- for (j = v->cheight; j > 0; --j) {
- for (i = 0; i < vplanes; i+=2)
- place[i] = ~place[i];
-
- place += v->planesiz;
- }
- v->curstimer = v->period;
- }
-
- /* make sure the cursor is off */
-
- INLINE
- static void
- curs_off(v)
- SCREEN *v;
- {
- if (v->flags & CURS_ON) {
- if (v->flags & CURS_FSTATE) {
- flash(v);
- v->flags &= ~CURS_FSTATE;
- }
- }
- }
-
- /* OK, show the cursor again (if appropriate) */
-
- INLINE static void
- curs_on(v)
- SCREEN *v;
- {
- if (v->hidecnt) return;
-
- if (v->flags & CURS_ON) {
- #if 0
- /* if the cursor is flashing, we cheat a little and leave it off
- * to be turned on again (if necessary) by the VBL routine
- */
- if (v->flags & CURS_FLASH) {
- v->curstimer = 2;
- return;
- }
- #endif
- if (!(v->flags & CURS_FSTATE)) {
- v->flags |= CURS_FSTATE;
- flash(v);
- }
- }
- }
-
- void
- init()
- {
- SCREEN *v;
- int i, j;
- char *data, *foo;
- static char chardata[256*16];
- register int linelen;
-
- foo = lineA0();
- v = (SCREEN *)(foo - 346);
-
- /* Ehem... The screen might be bigger than 32767 bytes.
- Let's do some casting...
- Erling
- */
- linelen = v->linelen;
- scrnsize = (v->maxy+1)*(long)linelen;
- rowoff = (char *)kmalloc((long)((v->maxy+1) * sizeof(long)));
- if (rowoff == 0) {
- FATAL("Insufficient memory for screen offset table!");
- } else {
- long off, *lptr = (long *)rowoff;
- for (i=0, off=0; i<=v->maxy; i++) {
- *lptr++ = off;
- off += linelen;
- }
- }
- if (hardscroll == -1) {
- /* request for auto-setting */
- hardscroll = v->maxy+1;
- }
- if (hardscroll > 0) {
- if (!hardbase)
- hardbase = (char *)(((long)kcore(SCNSIZE(v)+256L)+255L)
- & 0xffffff00L);
-
- if (hardbase == 0) {
- ALERT("Insufficient memory for hardware scrolling!");
- } else {
- v->curstimer = 0x7f;
- quickmove(hardbase, base, scrnsize);
- v->cursaddr = v->cursaddr + (hardbase - base);
- oldbase = base;
- base = hardbase;
- Setscreen(hardbase, hardbase, -1);
- v->curstimer = v->period;
- }
- }
- hardline = 0;
- if (v->cheight == 8 && v->planes == 2) {
- foo = &chardata[0];
- vpaint = paint8c;
- for (i = 0; i < 256; i++) {
- chartab[i] = foo;
- data = v->fontdata + i;
- for (j = 0; j < 8; j++) {
- *foo++ = *data;
- data += v->form_width;
- }
- }
- } else if ((v->cheight == 16 || v->cheight == 8) && v->planes == 1) {
- foo = &chardata[0];
- vpaint = paint816m;
- for (i = 0; i < 256; i++) {
- chartab[i] = foo;
- data = v->fontdata + i;
- for (j = 0; j < v->cheight; j++) {
- *foo++ = *data;
- data += v->form_width;
- }
- }
- }
- else
- vpaint = paint;
-
- if (v->hidecnt == 0) {
- /*
- * make sure the cursor is set up correctly and turned on
- */
- (void)Cursconf(0,0); /* turn cursor off */
-
- v->flags &= ~CURS_FSTATE;
-
- /* now turn the cursor on the way we like it */
- v->curstimer = v->period;
- v->hidecnt = 0;
- v->flags |= CURS_ON;
- curs_on(v);
- } else {
- (void)Cursconf(0,0);
- v->flags &= ~CURS_ON;
- v->hidecnt = 1;
- }
-
- current = v;
- /* setup bgmask and fgmask */
- setbgcol(v, v->bgcol);
- setfgcol(v, v->fgcol);
- state = normal_putch;
- }
-
- /*
- * PLACE(v, x, y): the address corresponding to the upper left hand corner of
- * the character at position (x,y) on screen v
- */
- INLINE static
- char *PLACE(v, x, y)
- SCREEN *v;
- int x, y;
- {
- char *place;
- int i, j;
-
- place = base + x;
- if (y == v->maxy)
- place += scrnsize - v->linelen;
- else if (y) {
- y+=y; /* Make Y into index for longword array. */
- y+=y; /* Two word-size adds are faster than a 2-bit shift. */
- place += *(long *)(rowoff + y);
- }
- if ((j = v->planes-1)) {
- i = (x & 0xfffe);
- do place += i;
- while (--j);
- }
- return place;
- }
-
- /*
- * paint(v, c, place): put character 'c' at position 'place' on screen
- * v. It is assumed that x, y are proper coordinates!
- * Specialized versions (paint8c and paint816m) of this routine follow;
- * they assume 8 line high characters, medium res. and 8 or 16 line/mono,
- * respectively.
- */
-
- static void
- paint(v, c, place)
- SCREEN *v;
- int c;
- char *place;
- {
- char *data, d, doinverse;
- ITYPE j, planecount;
- int vplanes;
- long vform_width, vplanesiz;
-
- vplanes = v->planes;
-
- data = v->fontdata + c;
- doinverse = (v->flags & FINVERSE) ? 0xff : 0;
- vform_width = v->form_width;
- vplanesiz = v->planesiz;
-
- for (j = v->cheight; j > 0; --j) {
- d = *data ^ doinverse;
- for (planecount = 0; planecount < vplanes; planecount++)
- place[planecount << 1]
- = ((d & (char) fgmask[planecount])
- | (~d & (char) bgmask[planecount]));
- place += vplanesiz;
- data += vform_width;
- }
- }
-
- static void
- paint8c(v, c, place)
- SCREEN *v;
- int c;
- char *place;
- {
- char *data;
- char d, doinverse;
- char bg0, bg1, fg0, fg1;
- long vplanesiz;
-
- data = chartab[c];
-
- doinverse = (v->flags & FINVERSE) ? 0xff : 0;
- vplanesiz = v->planesiz;
- bg0 = bgmask[0];
- bg1 = bgmask[1];
- fg0 = fgmask[0];
- fg1 = fgmask[1];
-
- if (!doinverse && !bg0 && !bg1 && fg0 && fg1) {
- /* line 1 */
- d = *data++;
- *place = d;
- place[2] = d;
- place += vplanesiz;
-
- /* line 2 */
- d = *data++;
- *place = d;
- place[2] = d;
- place += vplanesiz;
-
- /* line 3 */
- d = *data++;
- *place = d;
- place[2] = d;
- place += vplanesiz;
-
- /* line 4 */
- d = *data++;
- *place = d;
- place[2] = d;
- place += vplanesiz;
-
- /* line 5 */
- d = *data++;
- *place = d;
- place[2] = d;
- place += vplanesiz;
-
- /* line 6 */
- d = *data++;
- *place = d;
- place[2] = d;
- place += vplanesiz;
-
- /* line 7 */
- d = *data++;
- *place = d;
- place[2] = d;
- place += vplanesiz;
-
- /* line 8 */
- d = *data;
- *place = d;
- place[2] = d;
- } else {
- /* line 1 */
- d = *data++ ^ doinverse;
- *place = ((d & fg0) | (~d & bg0));
- place[2] = ((d & fg1) | (~d & bg1));
- place += vplanesiz;
-
- /* line 2 */
- d = *data++ ^ doinverse;
- *place = ((d & fg0) | (~d & bg0));
- place[2] = ((d & fg1) | (~d & bg1));
- place += vplanesiz;
-
- /* line 3 */
- d = *data++ ^ doinverse;
- *place = ((d & fg0) | (~d & bg0));
- place[2] = ((d & fg1) | (~d & bg1));
- place += vplanesiz;
-
- /* line 4 */
- d = *data++ ^ doinverse;
- *place = ((d & fg0) | (~d & bg0));
- place[2] = ((d & fg1) | (~d & bg1));
- place += vplanesiz;
-
- /* line 5 */
- d = *data++ ^ doinverse;
- *place = ((d & fg0) | (~d & bg0));
- place[2] = ((d & fg1) | (~d & bg1));
- place += vplanesiz;
-
- /* line 6 */
- d = *data++ ^ doinverse;
- *place = ((d & fg0) | (~d & bg0));
- place[2] = ((d & fg1) | (~d & bg1));
- place += vplanesiz;
-
- /* line 7 */
- d = *data++ ^ doinverse;
- *place = ((d & fg0) | (~d & bg0));
- place[2] = ((d & fg1) | (~d & bg1));
- place += vplanesiz;
-
- /* line 8 */
- d = *data ^ doinverse;
- *place = ((d & fg0) | (~d & bg0));
- place[2] = ((d & fg1) | (~d & bg1));
- }
- }
-
- static void
- paint816m(v, c, place)
- SCREEN *v;
- int c;
- char *place;
- {
- char *data;
- char d, doinverse;
- long vplanesiz;
-
- data = chartab[c];
- doinverse = (v->flags & FINVERSE) ? 0xff : 0;
- doinverse ^= bgmask[0];
- vplanesiz = v->planesiz;
-
- if (bgmask[0] == fgmask[0])
- {
- /* fgcol and bgcol are the same -- easy */
- d = (char) bgmask[0];
- *place = d;
- place += vplanesiz;
- *place = d;
- place += vplanesiz;
- *place = d;
- place += vplanesiz;
- *place = d;
- place += vplanesiz;
- *place = d;
- place += vplanesiz;
- *place = d;
- place += vplanesiz;
- *place = d;
- place += vplanesiz;
- *place = d;
- if (v->cheight == 8)
- return;
- place += vplanesiz;
- *place = d;
- place += vplanesiz;
- *place = d;
- place += vplanesiz;
- *place = d;
- place += vplanesiz;
- *place = d;
- place += vplanesiz;
- *place = d;
- place += vplanesiz;
- *place = d;
- place += vplanesiz;
- *place = d;
- place += vplanesiz;
- *place = d;
- }
- else if (!doinverse) {
- /* line 1 */
- d = *data++;
- *place = d;
- place += vplanesiz;
-
- /* line 2 */
- d = *data++;
- *place = d;
- place += vplanesiz;
-
- /* line 3 */
- d = *data++;
- *place = d;
- place += vplanesiz;
-
- /* line 4 */
- d = *data++;
- *place = d;
- place += vplanesiz;
-
- /* line 5 */
- d = *data++;
- *place = d;
- place += vplanesiz;
-
- /* line 6 */
- d = *data++;
- *place = d;
- place += vplanesiz;
-
- /* line 7 */
- d = *data++;
- *place = d;
- place += vplanesiz;
-
- /* line 8 */
- d = *data++;
- *place = d;
-
- if (v->cheight == 8)
- return;
-
- place += vplanesiz;
-
- /* line 9 */
- d = *data++;
- *place = d;
- place += vplanesiz;
-
- /* line 10 */
- d = *data++;
- *place = d;
- place += vplanesiz;
-
- /* line 11 */
- d = *data++;
- *place = d;
- place += vplanesiz;
-
- /* line 12 */
- d = *data++;
- *place = d;
- place += vplanesiz;
-
- /* line 13 */
- d = *data++;
- *place = d;
- place += vplanesiz;
-
- /* line 14 */
- d = *data++;
- *place = d;
- place += vplanesiz;
-
- /* line 15 */
- d = *data++;
- *place = d;
- place += vplanesiz;
-
- /* line 16 */
- d = *data;
- *place = d;
- } else {
- /* line 1 */
- d = ~*data++;
- *place = d;
- place += vplanesiz;
-
- /* line 2 */
- d = ~*data++;
- *place = d;
- place += vplanesiz;
-
- /* line 3 */
- d = ~*data++;
- *place = d;
- place += vplanesiz;
-
- /* line 4 */
- d = ~*data++;
- *place = d;
- place += vplanesiz;
-
- /* line 5 */
- d = ~*data++;
- *place = d;
- place += vplanesiz;
-
- /* line 6 */
- d = ~*data++;
- *place = d;
- place += vplanesiz;
-
- /* line 7 */
- d = ~*data++;
- *place = d;
- place += vplanesiz;
-
- /* line 8 */
- d = ~*data++;
- *place = d;
-
- if (v->cheight == 8)
- return;
-
- place += vplanesiz;
-
- /* line 9 */
- d = ~*data++;
- *place = d;
- place += vplanesiz;
-
- /* line 10 */
- d = ~*data++;
- *place = d;
- place += vplanesiz;
-
- /* line 11 */
- d = ~*data++;
- *place = d;
- place += vplanesiz;
-
- /* line 12 */
- d = ~*data++;
- *place = d;
- place += vplanesiz;
-
- /* line 13 */
- d = ~*data++;
- *place = d;
- place += vplanesiz;
-
- /* line 14 */
- d = ~*data++;
- *place = d;
- place += vplanesiz;
-
- /* line 15 */
- d = ~*data++;
- *place = d;
- place += vplanesiz;
-
- /* line 16 */
- d = ~*data;
- *place = d;
- }
- }
-
- /*
- * gotoxy (v, x, y): move current cursor address of screen v to (x, y)
- * makes sure that (x, y) will be legal
- */
-
- INLINE static void
- gotoxy(v, x, y)
- SCREEN *v;
- int x, y;
- {
- if (x > v->maxx) x = v->maxx;
- else if (x < 0) x = 0;
- if (y > v->maxy) y = v->maxy;
- else if (y < 0) y = 0;
-
- v->cx = x;
- v->cy = y;
- v->cursaddr = PLACE(v, x, y);
- }
-
- /*
- * clrline(v, r): clear line r of screen v
- */
-
- INLINE static void
- clrline(v, r)
- SCREEN *v;
- int r;
- {
- int *dst, *m;
- long nwords;
- int i, vplanes;
-
- /* Hey, again the screen might be bigger than 32767 bytes.
- Do another cast... */
- r += r;
- r += r;
- dst = (int *)(base + *(long *)(rowoff+r));
- if (v->bgcol == 0)
- zero((char *)dst, v->linelen);
- else
- {
- /* do it the hard way */
- vplanes = v->planes;
- for (nwords = v->linelen >> 1; nwords > 0; nwords -= vplanes)
- {
- m = bgmask;
- for (i = 0; i < vplanes; i++)
- *dst++ = *m++;
- }
- }
- }
-
- /*
- * clear(v): clear the whole screen v
- */
-
- INLINE static void
- clear(v)
- SCREEN *v;
- {
- int i, vplanes;
- int *dst, *m;
- long nwords;
-
- if (v->bgcol == 0)
- zero(base, scrnsize);
- else
- {
- /* do it the hard way */
- dst = (int *) base;
- vplanes = v->planes;
- for (nwords = scrnsize >> 1; nwords > 0; nwords -= vplanes)
- {
- m = bgmask;
- for (i = 0; i < vplanes; i++)
- *dst++ = *m++;
- }
- }
- }
-
- /*
- * clrchar(v, x, y): clear the (x,y) position on screen v
- */
-
- INLINE static void
- clrchar(v, x, y)
- SCREEN *v;
- int x, y;
- {
- int i, j, vplanes;
- char *place;
- int *m;
-
- vplanes = v->planes + v->planes;
-
- place = PLACE(v, x, y);
-
- for (j = v->cheight; j > 0; --j) {
- m = bgmask;
- for (i = 0; i < vplanes; i += 2)
- place[i] = (char) *m++;
- place += v->planesiz;
- }
- }
-
- /*
- * clrfrom(v, x1, y1, x2, y2): clear screen v from position (x1,y1) to
- * position (x2, y2) inclusive. It is assumed that y2 >= y1.
- */
-
- INLINE static void
- clrfrom(v, x1, y1, x2, y2)
- SCREEN *v;
- int x1,y1,x2,y2;
- {
- int i;
-
- for (i = x1; i <= v->maxx; i++)
- clrchar(v, i, y1);
- if (y2 > y1) {
- for (i = 0; i <= x2; i++)
- clrchar(v, i, y2);
- for (i = y1+1; i < y2; i++)
- clrline(v, i);
- }
- }
-
- /*
- * scroll a screen in hardware; if we still have hardware scrolling lines left,
- * just move the physical screen base, otherwise copy the screen back to the
- * hardware base and start over
- */
- void
- hardware_scroll(v)
- SCREEN *v;
- {
-
- ++hardline;
- if (hardline < hardscroll) { /* just move the screen */
- base += v->linelen;
- } else {
- hardline = 0;
- quickmove(hardbase, base + v->linelen, scrnsize - v->linelen);
- base = hardbase;
- }
- v->cursaddr = PLACE(v, v->cx, v->cy);
- Setscreen(base, base, -1);
- }
-
- /*
- * delete_line(v, r): delete line r of screen v. The screen below this
- * line is scrolled up, and the bottom line is cleared.
- */
-
- #define scroll(v) delete_line(v, 0)
-
- INLINE static void
- delete_line(v, r)
- SCREEN *v;
- int r;
- {
- long *src, *dst, nbytes;
-
- if (r == 0) {
- if (hardbase) {
- hardware_scroll(v);
- clrline(v, v->maxy);
- return;
- }
- nbytes = scrnsize - v->linelen;
- } else {
- register int i = v->maxy - r;
- i += i;
- i += i;
- nbytes = *(long *)(rowoff+i);
- }
-
- /* Sheeze, how many times do we really have to cast...
- Erling.
- */
-
- r += r;
- r += r;
- dst = (long *)(base + *(long *)(rowoff + r));
- src = (long *)( ((long)dst) + v->linelen);
-
- quickmove(dst, src, nbytes);
-
- /* clear the last line */
- clrline(v, v->maxy);
- }
-
- /*
- * insert_line(v, r): scroll all of the screen starting at line r down,
- * and then clear line r.
- */
-
- INLINE static void
- insert_line(v, r)
- SCREEN *v;
- int r;
- {
- long *src, *dst;
- int i, j, linelen;
-
- i = v->maxy - 1;
- i += i;
- i += i;
- j = r+r;
- j += j;
- linelen = v->linelen;
- src = (long *)(base + *(long *)(rowoff + i));
- dst = (long *)((long)src + linelen);
- for (; i >= j ; i -= 4) {
- /* move line i to line i+1 */
- quickmove(dst, src, linelen);
- dst = src;
- src = (long *)((long) src - linelen);
- }
-
- /* clear line r */
- clrline(v, r);
- }
-
- /*
- * special states for handling ESC b x and ESC c x. Note that for now,
- * color is ignored.
- */
-
- static void
- setbgcol(v, c)
- SCREEN *v;
- int c;
- {
- int i;
-
- v->bgcol = c & ((1 << v->planes)-1);
- for (i = 0; i < v->planes; i++)
- bgmask[i] = (v->bgcol & (1 << i)) ? -1 : 0;
- state = normal_putch;
- }
-
- static void
- setfgcol(v, c)
- SCREEN *v;
- int c;
- {
- int i;
-
- v->fgcol = c & ((1 << v->planes)-1);
- for (i = 0; i < v->planes; i++)
- fgmask[i] = (v->fgcol & (1 << i)) ? -1 : 0;
- state = normal_putch;
- }
-
- static void
- setcurs(v, c)
- SCREEN *v;
- int c;
- {
- c -= ' ';
- if (!c) {
- v->flags &= ~CURS_FLASH;
- } else {
- v->flags |= CURS_FLASH;
- v->period = (unsigned char) c;
- }
- state = normal_putch;
- }
-
- static void
- quote_putch(v, c)
- SCREEN *v;
- int c;
- {
- (*vpaint)(v, c, v->cursaddr);
- state = normal_putch;
- }
-
- /*
- * putesc(v, c): handle the control sequence ESC c
- */
-
- static void
- putesc(v, c)
- SCREEN *v;
- int c;
- {
- int i;
- int cx, cy;
-
- cx = v->cx; cy = v->cy;
-
- switch (c) {
- case 'A': /* cursor up */
- if (cy) {
- moveup: v->cy = --cy;
- v->cursaddr -= v->linelen;
- }
- break;
- case 'B': /* cursor down */
- if (cy < v->maxy) {
- v->cy = ++cy;
- v->cursaddr += v->linelen;
- }
- break;
- case 'C': /* cursor right */
- if (cx < v->maxx) {
- if ((i = v->planes-1) && (cx & 1))
- v->cursaddr += i + i;
- v->cx = ++cx;
- v->cursaddr++;
- }
- break;
- case 'D': /* cursor left */
- if (cx) {
- v->cx = --cx;
- v->cursaddr--;
- if ((i = v->planes-1) && (cx & 1))
- v->cursaddr -= i + i;
- }
- break;
- case 'E': /* clear home */
- clear(v);
- /* fall through... */
- case 'H': /* cursor home */
- v->cx = 0; v->cy = 0;
- v->cursaddr = base;
- break;
- case 'I': /* cursor up, insert line */
- if (cy == 0) {
- insert_line(v, 0);
- }
- else
- goto moveup;
- break;
- case 'J': /* clear below cursor */
- clrfrom(v, cx, cy, v->maxx, v->maxy);
- break;
- case 'K': /* clear remainder of line */
- clrfrom(v, cx, cy, v->maxx, cy);
- break;
- case 'L': /* insert a line */
- v->cx = 0;
- i = cy + cy;
- i += i;
- v->cursaddr = base + *(long *)(rowoff + i);
- insert_line(v, cy);
- break;
- case 'M': /* delete line */
- v->cx = 0;
- i = cy + cy;
- i += i;
- v->cursaddr = base + *(long *)(rowoff + i);
- delete_line(v, cy);
- break;
- case 'Q': /* EXTENSION: quote-next-char */
- state = quote_putch;
- return;
- case 'Y':
- state = escy_putch;
- return; /* YES, this should be 'return' */
-
- case 'b':
- state = setfgcol;
- return;
- case 'c':
- state = setbgcol;
- return;
- case 'd': /* clear to cursor position */
- clrfrom(v, 0, 0, cx, cy);
- break;
- case 'e': /* enable cursor */
- v->flags |= CURS_ON;
- v->hidecnt = 1; /* so --v->hidecnt shows the cursor */
- break;
- case 'f': /* cursor off */
- v->hidecnt++;
- v->flags &= ~CURS_ON;
- break;
- case 'j': /* save cursor position */
- v->savex = v->cx;
- v->savey = v->cy;
- break;
- case 'k': /* restore saved position */
- gotoxy(v, v->savex, v->savey);
- break;
- case 'l': /* clear line */
- v->cx = 0;
- i = cy + cy;
- i += i;
- v->cursaddr = base + *(long *)(rowoff + i);
- clrline(v, cy);
- break;
- case 'o': /* clear from start of line to cursor */
- clrfrom(v, 0, cy, cx, cy);
- break;
- case 'p': /* reverse video on */
- v->flags |= FINVERSE;
- break;
- case 'q': /* reverse video off */
- v->flags &= ~FINVERSE;
- break;
- case 't': /* EXTENSION: set cursor flash rate */
- state = setcurs;
- return;
- case 'v': /* wrap on */
- v->flags |= FWRAP;
- break;
- case 'w':
- v->flags &= ~FWRAP;
- break;
- }
- state = normal_putch;
- }
-
- /*
- * escy1_putch(v, c): for when an ESC Y + char has been seen
- */
- static void
- escy1_putch(v, c)
- SCREEN *v;
- int c;
- {
- gotoxy(v, c - ' ', escy1 - ' ');
- state = normal_putch;
- }
-
- /*
- * escy_putch(v, c): for when an ESC Y has been seen
- */
- static void
- escy_putch(v, c)
- SCREEN *v;
- int c;
- {
- UNUSED(v);
- escy1 = c;
- state = escy1_putch;
- }
-
- /*
- * normal_putch(v, c): put character 'c' on screen 'v'. This is the default
- * for when no escape, etc. is active
- */
-
- static void
- normal_putch(v, c)
- SCREEN *v;
- int c;
- {
- register int i;
-
- /* control characters */
- if (c < ' ') {
- switch (c) {
- case '\r':
- col0: v->cx = 0;
- i = v->cy + v->cy;
- i += i;
- v->cursaddr = base + *(long *)(rowoff + i);
- return;
- case '\n':
- if (v->cy == v->maxy) {
- scroll(v);
- } else {
- v->cy++;
- v->cursaddr += v->linelen;
- }
- return;
- case '\b':
- if (v->cx) {
- v->cx--;
- v->cursaddr--;
- if ((i = v->planes-1) && (v->cx & 1))
- v->cursaddr -= i+i;
- }
- return;
- case '\007': /* BELL */
- (void)bconout(CONDEV, 7);
- return;
- case '\033': /* ESC */
- state = putesc;
- return;
- case '\t':
- if (v->cx < v->maxx) {
- /* this can't be register for an ANSI compiler */
- union {
- long l;
- short i[2];
- } j;
- j.l = 0;
- j.i[1] = 8 - (v->cx & 7);
- v->cx += j.i[1];
- if (v->cx - v->maxx > 0) {
- j.i[1] = v->cx - v->maxx;
- v->cx = v->maxx;
- }
- v->cursaddr += j.l;
- if ((i = v->planes-1)) {
- if (j.l & 1)
- j.i[1]++;
- do v->cursaddr += j.l;
- while (--i);
- }
- }
- return;
- default:
- return;
- }
- }
-
- (*vpaint)(v, c, v->cursaddr);
- v->cx++;
- if (v->cx > v->maxx) {
- if (v->flags & FWRAP) {
- normal_putch(v, '\n');
- goto col0;
- } else {
- v->cx = v->maxx;
- }
- } else {
- v->cursaddr++;
- if ((i = v->planes-1) && !(v->cx & 1)) /* new word */
- v->cursaddr += i + i;
- }
- }
-
- INLINE static void
- put_ch(v, c)
- SCREEN *v;
- int c;
- {
- (*state)(v, c & 0x00ff);
- }
-
- static long ARGS_ON_STACK screen_open P_((FILEPTR *f));
- static long ARGS_ON_STACK screen_read P_((FILEPTR *f, char *buf, long nbytes));
- static long ARGS_ON_STACK screen_write P_((FILEPTR *f, const char *buf, long nbytes));
- static long ARGS_ON_STACK screen_lseek P_((FILEPTR *f, long where, int whence));
- static long ARGS_ON_STACK screen_ioctl P_((FILEPTR *f, int mode, void *buf));
- static long ARGS_ON_STACK screen_close P_((FILEPTR *f, int pid));
- static long ARGS_ON_STACK screen_select P_((FILEPTR *f, long p, int mode));
- static void ARGS_ON_STACK screen_unselect P_((FILEPTR *f, long p, int mode));
-
- extern long ARGS_ON_STACK null_datime P_((FILEPTR *f, short *time, int rwflag));
-
- DEVDRV screen_device = {
- screen_open, screen_write, screen_read, screen_lseek, screen_ioctl,
- null_datime, screen_close, screen_select, screen_unselect
- };
-
- static long ARGS_ON_STACK
- screen_open(f)
- FILEPTR *f;
- {
-
- if (!current) {
- init();
- }
- ++scr_usecnt;
-
- f->flags |= O_TTY;
- return 0;
- }
-
- static long ARGS_ON_STACK
- screen_close(f, pid)
- FILEPTR *f;
- int pid;
- {
- SCREEN *v = current;
- UNUSED(pid);
-
- if (v && f->links <= 0 && !--scr_usecnt) {
- if (hardbase) {
- v->curstimer = 0x7f;
- v->cursaddr = v->cursaddr + (oldbase-base);
- quickmove(oldbase, base, scrnsize);
- base = oldbase;
- Setscreen(oldbase, oldbase, -1);
- v->curstimer = v->period;
- }
- current = 0;
- }
- return 0;
- }
-
- static long ARGS_ON_STACK
- screen_write(f, buf, bytes)
- FILEPTR *f; const char *buf; long bytes;
- {
- SCREEN *v = current;
- struct bios_file *b = (struct bios_file *)f->fc.index;
- long *r;
- long ret = 0;
- int c;
-
- UNUSED(f);
-
- (void)checkkeys();
- v->hidecnt++;
- v->flags |= CURS_UPD; /* for TOS 1.0 */
- curs_off(v);
- r = (long *)buf;
- while (bytes > 0) {
- c = (int) *r++;
- put_ch(v, c);
- bytes -= 4; ret+= 4;
- }
- if (v->hidecnt > 0)
- --v->hidecnt;
- else
- v->hidecnt = 0;
- curs_on(v);
- v->flags &= ~CURS_UPD;
- if (ret > 0) {
- b->xattr.atime = b->xattr.mtime = timestamp;
- b->xattr.adate = b->xattr.mdate = datestamp;
- }
- return ret;
- }
-
- static long ARGS_ON_STACK
- screen_read(f, buf, bytes)
- FILEPTR *f; char *buf; long bytes;
- {
- struct bios_file *b = (struct bios_file *)f->fc.index;
- long *r, ret = 0;
-
- r = (long *)buf;
-
- while (bytes > 0) {
- if ( (f->flags & O_NDELAY) && !bconstat(CONDEV) )
- break;
- *r++ = bconin(CONDEV) & 0x7fffffffL;
- bytes -= 4; ret += 4;
- }
- if (ret > 0) {
- b->xattr.atime = timestamp;
- b->xattr.adate = datestamp;
- }
- return ret;
- }
-
- static long ARGS_ON_STACK
- screen_lseek(f, where, whence)
- FILEPTR *f;
- long where;
- int whence;
- {
- /* terminals always are at position 0 */
- UNUSED(f); UNUSED(where);
- UNUSED(whence);
- return 0;
- }
-
- static long ARGS_ON_STACK
- screen_ioctl(f, mode, buf)
- FILEPTR *f; int mode; void *buf;
- {
- long *r = (long *)buf;
- struct winsize *w;
-
- UNUSED(f);
-
- if (mode == FIONREAD) {
- if (bconstat(CONDEV))
- *r = 1;
- else
- *r = 0;
- }
- else if (mode == FIONWRITE) {
- *r = 1;
- }
- else if (mode == TIOCFLUSH) {
- /* BUG: this should flush the input/output buffers */
- return 0;
- }
- else if (mode == TIOCGWINSZ) {
- w = (struct winsize *)buf;
- w->ws_row = current->maxy+1;
- w->ws_col = current->maxx+1;
- }
- else if (mode >= TCURSOFF && mode <= TCURSGRATE) {
- SCREEN *v = current;
- switch(mode) {
- case TCURSOFF:
- curs_off(v);
- v->hidecnt++;
- v->flags &= ~CURS_ON;
- break;
- case TCURSON:
- v->flags |= CURS_ON;
- v->hidecnt = 0;
- curs_on(v);
- break;
- case TCURSBLINK:
- curs_off(v);
- v->flags |= CURS_FLASH;
- curs_on(v);
- break;
- case TCURSSTEADY:
- curs_off(v);
- v->flags &= ~CURS_FLASH;
- curs_on(v);
- break;
- case TCURSSRATE:
- v->period = *((short *)buf);
- break;
- case TCURSGRATE:
- return v->period;
- }
- } else
- return EINVFN;
-
- return 0;
- }
-
- static long ARGS_ON_STACK
- screen_select(f, p, mode)
- FILEPTR *f; long p; int mode;
- {
- struct tty *tty = (struct tty *)f->devinfo;
- int dev = CONDEV;
-
- if (mode == O_RDONLY) {
- if (bconstat(dev)) {
- return 1;
- }
- if (tty) {
- /* avoid collisions with other processes */
- if (!tty->rsel)
- tty->rsel = p;
- }
- return 0;
- } else if (mode == O_WRONLY) {
- return 1;
- }
- /* default -- we don't know this mode, return 0 */
- return 0;
- }
-
- static void ARGS_ON_STACK
- screen_unselect(f, p, mode)
- FILEPTR *f;
- long p;
- int mode;
- {
- struct tty *tty = (struct tty *)f->devinfo;
-
- if (tty) {
- if (mode == O_RDONLY && tty->rsel == p)
- tty->rsel = 0;
- else if (mode == O_WRONLY && tty->wsel == p)
- tty->wsel = 0;
- }
- }
-
- #endif /* FASTTEXT */
-